import os
import subprocess
import json
import shutil

import mconfig



class Ldmnq(mconfig.Mnqconfig):
    sux=".ldbk"
    url="https://res.ldmnq.com/gw/assets/images/05/favicon.ico"
    name="雷电模拟器"
    def __init__(self):
        pass

    def quit(self, index):
        ''' 退出 <--name mnq_name | --index mnq_idx> '''
        return self._shell_cmd(["quit", "--index", index])

    def quitall(self):
        ''' 退出所有 ''' 
        return self._shell_cmd(["quitall"])

    def launch(self, index):
        ''' 启动 <--name mnq_name | --index mnq_idx> '''
        return self._shell_cmd(["launch", "--index", index])

    def reboot(self, index):
        ''' 重启 <--name mnq_name | --index mnq_idx> '''
        return self._shell_cmd(["reboot", "--index", index])

    def list(self):
        ''' 列表信息 '''
        ret = self._shell_cmd(["list"])
        if not ret:
            return []
        return ret.split("\n")

    def runninglist(self):
        ''' 运行列表信息 '''
        ret = self._shell_cmd(["runninglist"])
        if not ret:
            return []
        return ret.split("\n")

    def isrunning(self, index):
        ''' 判断是否启动 <--name mnq_name | --index mnq_idx> '''
        return self._shell_cmd([
            "isrunning",
            "--index",
            index])

    def list2(self):
        ''' 列表信息 '''
        ret = self._shell_cmd(["list2"])
        dic = {}
        if not ret:
            return dic
        for i in ret.split("\n"):
            if i:
                p = i.split(",")
                dic.update({ p[0]: {
                    "id": p[0],
                    "name": p[1],
                    "hwnd": int(p[2]),
                    "isrunning": p[4] == "1"}})
        return dic

    def add(self, name):
        ''' 添加 [--name <mnq_name>] '''
        return self._shell_cmd([
            "add",
            "--name",
            name])

    def copy(self, index, name):
        ''' 复制 [--name <mnq_name>] --from <mnq_name | mnq_idx> '''
        return self._shell_cmd([
            "copy",
            "--name",
            name,
            "--from",
            index], 180)

    def remove(self, index):
        ''' 删除 <--name mnq_name | --index mnq_idx> '''
        return self._shell_cmd([
            "remove",
            "--index",
            index])

    def rename(self, index, title):
        ''' 重命名 [--name <mnq_name | --index mnq_idx>] --title <mnq_title> '''
        return self._shell_cmd([
            "rename",
            "--index",
            index,
            "--title",
            title])

    def modify(self, index, dic):
        ''' 修改配置 <--name mnq_name | --index mnq_idx>
           [--resolution <w,h,dpi>]
           [--cpu <1 | 2 | 3 | 4>]
           [--memory <256 | 512 | 768 | 1024 | 1536 | 2048 | 4096 | 8192>]
           [--manufacturer asus]
           [--model ASUS_Z00DUO]
           [--pnumber 13800000000]
           [--imei <auto | 865166023949731>]
           [--imsi <auto | 460000000000000>]
           [--simserial <auto | 89860000000000000000>]
           [--androidid <auto | 0123456789abcdef>]
           [--mac <auto | 000000000000>]
           [--autorotate <1 | 0>
           [--lockwindow <1 | 0>
        '''
        stappend = []
        if type(dic) == dict:
            for i in dic:
                if i in ["resolution", "cpu", "memory", "manufacturer", "model", "pnumber"]:
                    stappend.append("--" + i)
                    stappend.append(dic[i])
        elif type(dic) == str:
            for i in mconfig.parse_string(dic):
                stappend.append("--" + i[0])
                stappend.append(",".join(i[1:]))
        return self._shell_cmd(["modify", "--index", index] + stappend)

    def installapp_filename(self, index, apk_file_name):
        ''' 安装apk <--name mnq_name | --index mnq_idx> --filename <apk_file_name> '''
        return self._shell_cmd([
            "installapp",
            "--index",
            index,
            "--filename",
            apk_file_name])

    def installapp_packagename(self, index, apk_package_name):
        ''' <--name mnq_name | --index mnq_idx> --packagename <apk_package_name> '''
        return self._shell_cmd([
            "installapp",
            "--index",
            index,
            "--packagename",
            apk_package_name])

    def uninstallapp(self, index, apk_package_name):
        ''' 卸载apk <--name mnq_name | --index mnq_idx> --packagename <apk_package_name> '''
        return self._shell_cmd([
            "uninstallapp",
            "--index",
            index,
            "--packagename",
            apk_package_name])

    def runapp(self, index, apk_package_name):
        ''' 启动apk <--name mnq_name | --index mnq_idx> --packagename <apk_package_name> '''
        return self._shell_cmd([
            "runapp",
            "--index",
            index,
            "--packagename",
            apk_package_name])

    def killapp(self, index, apk_package_name):
        ''' 杀死apk <--name mnq_name | --index mnq_idx> --packagename <apk_package_name> '''
        return self._shell_cmd([
            "killapp",
            "--index",
            index,
            "--packagename",
            apk_package_name])

    def locate(self, index, lat):
        ''' <--name mnq_name | --index mnq_idx> --LLI <Lng,Lat> '''
        return self._shell_cmd([
            "locate",
            "--index",
            index, 
            "--LLI", 
            lat])

    def adb(self, index, command):
        ''' adb命令 <--name mnq_name | --index mnq_idx> --command <cmd_str> '''
        return self._shell_cmd([
            "adb",
            "--index",
            index,
            "--command", 
            command])

    def setprop(self, index, key, value):
        ''' <--name mnq_name | --index mnq_idx> --key <name> --value <val> '''
        return self._shell_cmd([
            "setprop",
            "--index",
            index,
            "--key", 
            key, 
            "--value",
            value])

    def getprop(self, index, value):
        ''' <--name mnq_name | --index mnq_idx> [--key <name>] '''
        return self._shell_cmd([
            "getprop",
            "--index",
            index,
            "--key", 
            value])

    def downcpu(self, index, value):
        ''' <--name mnq_name | --index mnq_idx> --rate <0~100> '''
        return self._shell_cmd([
            "downcpu",
            "--index",
            index,
            "--rate",
            value])

    def backup(self, index, filepath):
        ''' 备份 <--name mnq_name | --index mnq_idx> --file <filepath> '''
        return self._shell_cmd([
            "backup",
            "--index",
            index,
            "--file",
            filepath], 180)

    def restore(self, index, filepath):
        ''' 还原 <--name mnq_name | --index mnq_idx> --file <filepath> '''
        return self._shell_cmd([
            "restore",
            "--index",
            index,
            "--file",
            filepath], 180)

    def action(self, index, key, value):
        ''' <--name mnq_name | --index mnq_idx> --key <name> --value <val> '''
        return self._shell_cmd([
            "action",
            "--index",
            index,
            "--key",
            key,
            "--value",
            value])

    def scan(self, index, filepath):
        ''' <--name mnq_name | --index mnq_idx> --file <filepath> '''
        return self._shell_cmd([
            "scan",
            "--index",
            index,
            "--file",
            filepath])

    def sortWnd(self):
        ''' '''
        return self._shell_cmd(["sortWnd"])

    def zoomIn(self):
        ''' '''
        return self._shell_cmd(["zoomIn"])

    def zoomOut(self):
        ''' '''
        return self._shell_cmd(["zoomOut"])

    def pull(self, index, filepath):
        ''' <--name mnq_name | --index mnq_idx> --remote <filepath> --local <filepath> '''
        return self._shell_cmd([
            "pull",
            "--index",
            index,
            "--remote",
            filepath,
            "--local", 
            filepath])

    def push(self, index, filepath):
        ''' <--name mnq_name | --index mnq_idx> --remote <filepath> --local <filepath> '''
        return self._shell_cmd([
            "push",
            "--index",
            index,
            "--remote",
            filepath,
            "--local",
            filepath])

    def backupapp(self, index, apk_package_name, filepath):
        ''' 备份apk <--name mnq_name | --index mnq_idx> --packagename <apk_package_name> --file <filepath> '''
        return self._shell_cmd([
            "backupapp",
            "--index",
            index,
            "--packagename",
            apk_package_name,
            "--file",
            filepath], 90)

    def restoreapp(self, index, apk_package_name, filepath):
        ''' 还原apk <--name mnq_name | --index mnq_idx> --packagename <apk_package_name> --file <filepath> '''
        return self._shell_cmd([
            "restoreapp",
            "--index",
            index,
            "--packagename",
            apk_package_name,
            "--file", 
            filepath], 90)

    def globalsetting(self):
        ''' [--fps <0~60>] [--audio <1 | 0>] [--fastplay <1 | 0>] [--cleanmode <1 | 0>] '''
        #self._shell_cmd(" globalsetting --index {} --packagename {} --file {}".format(name,filepath))
        pass

    def launchex(self, index, apk_package_name):
        ''' <--name mnq_name | --index mnq_idx> --packagename <apk_package_name> '''
        return self._shell_cmd([
            "launchex",
            "--index",
            index,
            "--packagename", 
            apk_package_name])

    def call_keyboard(self, index, keyboard):
        ''' 启动按键精灵 '''
        return self._shell_cmd([
            "action",
            "--index",
            index,
            "--key",
            "call.keyboard",
            "--value", 
            keyboard])

    def _shell_cmd(self, command, timeout=None):
        if timeout:
            self.timeout = timeout
        return shell_wondow([os.path.join(self.path, self.cmd)] + command, self.timeout)

    @staticmethod
    def get_file_list(path):
        return [v.replace("leidian", "") for v in os.listdir(os.path.join(path, "vms")) if "leidian" in v ]

    @staticmethod
    def del_file_index(path, index):
        mnq_path = os.path.join(os.path.join(path, "vms"), "leidian{}".format(index))
        try:
            if os.path.exists(mnq_path):
                shutil.rmtree(mnq_path)
                os.remove(os.path.join(path, "vms", "config", "leidian{}.config".format(index)))
        except:
            pass

    @staticmethod
    def set_cfg(path, index, key, data):
        config_path = os.path.join(path, "vms", "config", "leidian{}.config".format(index))
        with open(config_path, "r", encoding="utf-8") as f:
            json_data = json.load(f)

        cfgdict = {
            "model_imsi": "propertySettings.phoneIMSI",
            "model_shared": "statusSettings.sharedPictures",
            "model_playername": "statusSettings.playerName",
        }
        json_data[cfgdict[key]] = data[key]

        with open(config_path, "w", encoding="utf-8") as f:
            json.dump(json_data, f, ensure_ascii=False, indent=4)

    @staticmethod
    def get_cfg(path, index):
        cfg_path = os.path.join(path, "vms", "config", "leidian{}.config".format(index))
        result = {
            "model_imsi": "",
            "model_playername": "雷电模拟器",
            "model_shared": f"C:\\Users\\{os.environ['USERNAME']}\\Documents\\leidian\\Pictures",
        }
        if not os.path.exists(cfg_path):
            return result
        try:
            with open(cfg_path, "r", encoding='utf-8') as f:
                for key, value in json.loads(f.read()).items():
                    result[key] = value
                result["model_imsi"] = result.get("propertySettings.phoneIMSI", "")
                result["model_shared"] = result.get("statusSettings.sharedPictures", result["model_shared"])
                if result.get("statusSettings.playerName") != "":
                    result["model_playername"] = result.get("statusSettings.playerName", "雷电模拟器")
        except Exception:
            pass
        return result

    @staticmethod
    def get_size(path, index):
        mnq_path = os.path.join(path, "vms", "leidian{}".format(index))
        size_in_bytes = 0
        for vmdk in [os.path.join(mnq_path, "data.vmdk"), os.path.join(mnq_path, "sdcard.vmdk"), os.path.join(mnq_path, "system.vmdk")]:
            if os.path.exists(vmdk):
                size_in_bytes += os.path.getsize(vmdk)
        return round(size_in_bytes/(1024 * 1024 * 1024), 2)

    @staticmethod
    def getcmdline(args):
        path, index = args[0], args[1]
        mid = index.split("|")[0].split("=")[1]
        cmd_path = os.path.dirname(path)
        return mid, cmd_path



def shell_wondow(args, timeout):
    try:
        result = subprocess.run(args, 
            timeout=timeout,
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE,
            encoding='gbk',
            shell=True)
        return result.stdout
    except subprocess.TimeoutExpired as e:
        mconfig.err_log(e)
        return None
    except subprocess.CalledProcessError as e:
        mconfig.err_log(e)
        return None
